package org.jeecg.modules.operations.assistant.wechat.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.wechat.pay.java.core.exception.ServiceException;
import com.wechat.pay.java.core.notification.NotificationConfig;
import com.wechat.pay.java.core.notification.NotificationParser;
import com.wechat.pay.java.core.notification.RequestParam;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.modules.operations.assistant.wechat.entity.WXPayOrderReqVO;
import org.jeecg.modules.operations.assistant.wechat.entity.WxPayRespVO;
import org.jeecg.modules.operations.assistant.wechat.entity.WxPayV3Bean;
import org.jeecg.modules.operations.assistant.wechat.service.IWeChatPayService;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import com.wechat.pay.java.core.Config;
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import org.jeecg.modules.operations.assistant.wechat.service.QuickStart;
import org.jeecg.modules.operations.assistant.wechat.util.WXPayUtil;
import org.jeecg.modules.operations.assistant.xcbd.entity.XcbdCollectionRecord;
import org.jeecg.modules.operations.assistant.xcbd.entity.XcbdSalesContract;
import org.jeecg.modules.operations.assistant.xcbd.mapper.XcbdCollectionRecordMapper;
import org.jeecg.modules.operations.assistant.xcbd.mapper.XcbdSalesContractMapper;
import org.jeecg.modules.system.service.ISysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import com.wechat.pay.java.service.payments.jsapi.JsapiService;
import com.wechat.pay.java.service.payments.jsapi.model.PrepayRequest;
import com.wechat.pay.java.service.payments.jsapi.model.Amount;
import com.wechat.pay.java.service.payments.jsapi.model.Payer;
import com.wechat.pay.java.service.payments.jsapi.model.PrepayResponse;
import com.wechat.pay.java.service.payments.model.Transaction;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static com.wechat.pay.java.core.http.Constant.*;

@Service
@Slf4j
public class WeChatPayServiceImpl implements IWeChatPayService {
    @Autowired
    private WxPayV3Bean wxPayV3Bean;
    @Autowired
    private XcbdCollectionRecordMapper xcbdCollectionRecordMapper;
    @Autowired
    private XcbdSalesContractMapper xcbdSalesContractMapper;
    @Override
    public WxPayRespVO createOrder(WXPayOrderReqVO payOrderReq) throws Exception {
        try {
            LambdaQueryWrapper<XcbdCollectionRecord> queryWrapper = new LambdaQueryWrapper<XcbdCollectionRecord>();
//            queryWrapper.eq(XcbdCollectionRecord::getPaymentMethod, "2");   //付款方式 2 微信
            queryWrapper.eq(XcbdCollectionRecord::getOrderNumber, payOrderReq.getOrderSn());     // 订单号
//            queryWrapper.eq(XcbdCollectionRecord::getTradeState, "NOTPAY");     // 订单未支付
//        String[] tradeStateArray = {"SUCCESS","REFUND","CLOSED","REVOKED","PAYERROR"};
//        Collection<String> tradeStates = Arrays.asList(tradeStateArray);
//        queryWrapper.notIn(XcbdCollectionRecord::getTradeState, tradeStates);
            List<XcbdCollectionRecord> collectionRecordList = xcbdCollectionRecordMapper.selectList(queryWrapper);
            if(collectionRecordList != null && collectionRecordList.size()>0) {
                XcbdCollectionRecord collectionRecord = collectionRecordList.get(0);
                BigDecimal amountCollected = collectionRecord.getAmountCollected();
                XcbdSalesContract xcbdSalesContract = xcbdSalesContractMapper.selectById(collectionRecord.getSalesContractId());
                String paymentType2="";
                if(collectionRecord.getPaymentMethod().equals("2")){ //微信支付
                    // 使用微信扫描 code_url 对应的二维码，即可体验Native支付
                    String paymentType= collectionRecord.getPaymentType();

                    if(paymentType.equals("0")){  //定金
                        paymentType2="定金";
                    } else if(paymentType.equals("1")){  //尾款
                        paymentType2="尾款";
                    }else {  // 2 全款
                        paymentType2="全款";
                    }
                }
                // 使用自动更新平台证书的RSA配置
                // 一个商户号只能初始化一个配置，否则会因为重复的下载任务报错
                Config config =
                        new RSAAutoCertificateConfig.Builder()
                                .merchantId(wxPayV3Bean.getMchId())
                                .privateKeyFromPath(wxPayV3Bean.getKeyPath())
                                .merchantSerialNumber(wxPayV3Bean.getMchSerialNo())
                                .apiV3Key(wxPayV3Bean.getApiKey())
                                .build();
                // 构建service
                JsapiService service = new JsapiService.Builder().config(config).build();
                // request.setXxx(val)设置所需参数，具体参数可见Request定义
                PrepayRequest request = new PrepayRequest();
                Amount amount = new Amount();
                amount.setTotal(amountCollected.intValue()*100);  // 金额
                request.setAmount(amount);
                request.setAppid(wxPayV3Bean.getAppId());
                request.setMchid(wxPayV3Bean.getMchId());
                request.setDescription(xcbdSalesContract.getCustomerName()+"支付合同"+paymentType2);  // 商品描述
                request.setNotifyUrl(wxPayV3Bean.getNotifyUrl());
                request.setOutTradeNo(collectionRecord.getOrderNumber());  // 订单号
                request.setAttach(collectionRecord.getId());   // 收款记录ID
                Payer payer = new Payer();
                payer.setOpenid(payOrderReq.getOpenId());   // OpenID
                request.setPayer(payer);
                // 调用下单方法，得到应答
                PrepayResponse response = service.prepay(request);
                WxPayRespVO vo = new WxPayRespVO();
                vo.setAppId(wxPayV3Bean.getAppId());
                Long timeStamp = System.currentTimeMillis() / 1000;
                vo.setTimeStamp(timeStamp);
                String substring = UUID.randomUUID().toString().replaceAll("-", "").substring(0, 32);
                vo.setNonceStr(substring);
                String signatureStr = Stream.of(wxPayV3Bean.getAppId(), String.valueOf(timeStamp), substring, "prepay_id=" + response.getPrepayId())
                        .collect(Collectors.joining("\n", "", "\n"));
                String sign = WXPayUtil.getSign(signatureStr, wxPayV3Bean.getKeyPath());
                vo.setPaySign(sign);
                vo.setPrepayId("prepay_id=" + response.getPrepayId());
                return vo;
            }
        }catch (ServiceException e){
            JSONObject parse = JSONObject.parseObject(e.getResponseBody());
//            throw new ResultException(ResultEnum.ERROR,parse.getString("message"));
        }catch (Exception e) {
//            throw new ResultException(ResultEnum.ERROR, e.toString());
        }
        return null;
    }

    @Override
    public void payNotify(HttpServletRequest request) {
        try {
            //读取请求体的信息
            ServletInputStream inputStream = request.getInputStream();
            StringBuffer stringBuffer = new StringBuffer();
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
            String s;
            //读取回调请求体
            while ((s = bufferedReader.readLine()) != null) {
                stringBuffer.append(s);
            }
            String s1 = stringBuffer.toString();
            String timestamp = request.getHeader(WECHAT_PAY_TIMESTAMP);
            String nonce = request.getHeader(WECHAT_PAY_NONCE);
            String signType = request.getHeader("Wechatpay-Signature-Type");
            String serialNo = request.getHeader(WECHAT_PAY_SERIAL);
            String signature = request.getHeader(WECHAT_PAY_SIGNATURE);
            // 如果已经初始化了 RSAAutoCertificateConfig，可直接使用
            // 没有的话，则构造一个
//            log.error(com.alibaba.fastjson2.JSON.toJSONString(wxPayV3Bean));
            NotificationConfig config = new RSAAutoCertificateConfig.Builder()
                    .merchantId(wxPayV3Bean.getMchId())
                    .privateKeyFromPath(wxPayV3Bean.getKeyPath())
                    .merchantSerialNumber(wxPayV3Bean.getMchSerialNo())
                    .apiV3Key(wxPayV3Bean.getApiKey())
                    .build();
            // 初始化 NotificationParser
            NotificationParser parser = new NotificationParser(config);
            RequestParam requestParam=new RequestParam.Builder()
                    .serialNumber(serialNo)
                    .nonce(nonce)
                    .signature(signature)
                    .timestamp(timestamp)
                    // 若未设置signType，默认值为 WECHATPAY2-SHA256-RSA2048
                    .signType(signType)
                    .body(s1)
                    .build();
            Transaction transaction = parser.parse(requestParam, Transaction.class);
            log.info("payNotify===={}", transaction);
            String tradeState = transaction.getTradeState().name();
            LambdaQueryWrapper<XcbdCollectionRecord> queryWrapper = new LambdaQueryWrapper<XcbdCollectionRecord>();
            queryWrapper.eq(XcbdCollectionRecord::getOrderNumber, transaction.getOutTradeNo());   //订单号
            List<XcbdCollectionRecord> collectionRecordList = xcbdCollectionRecordMapper.selectList(queryWrapper);
            if (collectionRecordList != null && collectionRecordList.size() > 0) {
                XcbdCollectionRecord collectionRecord = collectionRecordList.get(0);
                collectionRecord.setTradeState(tradeState);
                collectionRecord.setTradeStateDesc(transaction.getTradeStateDesc());
                xcbdCollectionRecordMapper.updateById(collectionRecord);
            }
        } catch (Exception e) {
            log.info("payNotify,ResultException={}", e.toString());
        }
    }
}